
package com.hlkj.pay.app.merchant.ext.impl.fuyou.ext;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import cn.hutool.core.bean.BeanUtil;
import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.extension.annotation.Extension;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderQueryContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelRefundPayOrderContext;
import com.hlkj.pay.app.merchant.ext.impl.fuyou.FuYouExtConstant;
import com.hlkj.pay.app.merchant.ext.impl.fuyou.FuYouScenePayOrderExtPt;
import com.hlkj.pay.app.merchant.ext.impl.fuyou.constant.FuYouConstant;
import com.hlkj.pay.app.merchant.ext.impl.fuyou.dto.FuYouAppChannelParams;
import com.hlkj.pay.app.merchant.ext.impl.fuyou.dto.FuYouConfig;
import com.hlkj.pay.app.merchant.ext.impl.fuyou.dto.FuYouPayOrderResultDto;
import com.hlkj.pay.app.merchant.ext.impl.fuyou.utils.HttpUtils;
import com.hlkj.pay.app.merchant.ext.impl.fuyou.utils.SignUtils;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.infrastructure.model.pay.ProviderChannelConfigDO;
import com.hlkj.pay.util.MerchantUtils;
import com.hlkj.pay.vo.order.req.PayOrderCommonParamReq;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * 条码支付，商户扫用户二维码收款
 * 
 * @author HlpayTeam
 * @date 2024/11/18 13:08
 */
@Slf4j
@Repository
@RequiredArgsConstructor
@Extension(bizId = FuYouExtConstant.SCAN_PAY)
public class FuYouScanPayOrderExtPt extends FuYouSceneCommonPayOrder implements FuYouScenePayOrderExtPt {

    @Override
    public void submitChannelPayOrder(ChannelPayOrderContext channelPayOrderContext) {
        ProviderChannelConfigDO providerChannelConfigDO = channelPayOrderContext.getProviderChannelConfigDO();
        String channelConfig = providerChannelConfigDO.getParamsConfig();
        // 配置转换
        FuYouConfig fuYouConfig = JsonUtils.parseObject(channelConfig, FuYouConfig.class);
        PayOrderDO payOrderDO = channelPayOrderContext.getPayOrderDO();
        MerchantAppChannelDO merchantAppChannelDO = channelPayOrderContext.getMerchantAppChannelDO();
        FuYouAppChannelParams fuYouAppChannelParams = fuYouAppChannelParams(merchantAppChannelDO);
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("version", "1.0");
            params.put("ins_cd", fuYouConfig.getInsCd());
            params.put("mchnt_cd", fuYouAppChannelParams.getFuYouId());
            params.put("term_id", "88888888");
            params.put("random_str", System.currentTimeMillis() + "");
            String payType = payOrderDO.getPayType();
            PayEnums.PAY_TYPE fromByType = PayEnums.PAY_TYPE.fromByType(payType);
            String orderType = payType;
            switch (fromByType) {
                case UNION_APY:
                    orderType = "UNIONPAY";
                    break;
            }
            params.put("order_type", orderType);
            params.put("goods_des", payOrderDO.getSubject());
            params.put("goods_detail", payOrderDO.getDescription());
            params.put("addn_inf", "");
            params.put("mchnt_order_no", payOrderDO.getPayOrderNo());
            params.put("curr_type", "CNY");
            params.put("order_amt", MerchantUtils.YuanToFen(payOrderDO.getAmount()).toString());
            params.put("term_ip", payOrderDO.getClientIp());
            params.put("txn_begin_ts", date(payOrderDO.getCreateTime()));
            params.put("goods_tag", "");
            PayOrderCommonParamReq.Extra extra = JsonUtils.parseObject(payOrderDO.getExtra(), PayOrderCommonParamReq.Extra.class);
            params.put("auth_code", extra.getAuthCode());
            params.put("sence", "1");

            params.put("reserved_expire_minute", expireMinute(payOrderDO.getExpiredTime()).toString());
            params.put("sign", SignUtils.getPaySign(params, fuYouConfig));
            log.info("富友条码支付参数:{}", JsonUtils.toJsonString(params));
            String mapToXml = SignUtils.convertMapToXml(params);
            log.info("富友条码支付请求xml参数:{}", mapToXml);
            Map<String, String> requestParams = new HashMap<>();
            mapToXml = URLEncoder.encode(mapToXml, FuYouConstant.charset);
            requestParams.put("req", mapToXml);
            String url = domain(channelPayOrderContext.isTest()) + FuYouConstant.MERCHANT_PAY_ORDER_QR;
            log.info("富友条码支付req参数:{}", JsonUtils.toJsonString(requestParams));
            String response = HttpUtils.post(url, requestParams);
            // 发起请求
            // FuYouPayOrderResultDto fuYouPayOrderResultDto = SignUtils.xmlToObject(response, FuYouPayOrderResultDto.class);
            Map<String, Object> stringObjectMap = SignUtils.xmlToObject(response);
            FuYouPayOrderResultDto fuYouPayOrderResultDto= BeanUtil.mapToBean(stringObjectMap,FuYouPayOrderResultDto.class,true);
            log.info("富友条码支付返回参数:{}", JsonUtils.toJsonString(fuYouPayOrderResultDto));
            if ("000000".equals(fuYouPayOrderResultDto.getResult_code())) {
                // channelPayOrderContext.setPayInfo(fuYouPayOrderResultDto.getQr_code());
                // channelPayOrderContext.setPayDataType("pay_url");
                channelPayOrderContext.setChannelOrderNo(fuYouPayOrderResultDto.getReserved_fy_order_no());
                channelPayOrderContext.setChannelOrderId(fuYouPayOrderResultDto.getReserved_channel_order_id());
            }
            else {
                String respDesc = fuYouPayOrderResultDto.getResult_msg();
                channelPayOrderContext.setProcessStatus(Boolean.FALSE);
                if (StringUtils.hasText(respDesc)) {
                    channelPayOrderContext.setRemark(respDesc);
                }
                else {
                    channelPayOrderContext.setRemark("富友提交条码支付查询返回错误信息为空,错误码为:" + fuYouPayOrderResultDto.getResult_code());
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("富友提交条码支付请求失败 message:{}", e.getMessage(), e);
            channelPayOrderContext.setRemark("富友提交条码支付请求失败,失败信息" + e.getMessage());
            channelPayOrderContext.setProcessStatus(Boolean.FALSE);
            // channelMerchantAccessQueryContext.setAccessStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.APPROVE_REFUSE);
        }
    }

    @Override
    public void queryChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonQueryChannelPayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void closeChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonCloseChannelPayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void queryChannelClosePayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonQueryChannelClosePayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void refundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        commonRefundChannelPayOrder(channelRefundPayOrderContext);
    }

    @Override
    public void queryRefundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        commonQueryRefundChannelPayOrder(channelRefundPayOrderContext);
    }

    @Override
    public boolean refundApply(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        return true;
    }

    @Override
    public CommonResult<String> channelOrderCode(ChannelPayOrderContext channelPayOrderContext) {
        return CommonResult.success();
    }

}
